package wiiusej.hardwareControllers;

import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;

import wiiusej.Wiimote;
import wiiusej.apptest.generalTasks.ActivateSpeaker;
import wiiusej.apptest.generalTasks.VolumeSpeakerTask;
import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent;

public class HardwareManagerImpl extends Thread implements HardwareManager{

	private static final int NTHREADS = 100;
	
	private static final ExecutorService executor = 
		Executors.newFixedThreadPool(NTHREADS);	
	
	//Hash map wich controls the status of the hardware components of wiimote
	private static WiimoteStatus wiimoteStatus = new WiimoteStatus(); 
	
	//WIIMOTE object
	private static Wiimote wiimote;
	
	//RealTimeFeedback, Rumble and LED communication queues
	private static BlockingQueue<Integer> fromRealToSoundQ;
	private static BlockingQueue<Integer> toRumbleQ;
	private static BlockingQueue<Integer> toLEDQ;
	
	
	public HardwareManagerImpl(Wiimote wiimote,
			BlockingQueue<Integer> fromRealToSoundQ, BlockingQueue<Integer> toRumbleQ, BlockingQueue<Integer> toLEDQ){
		
		this.wiimote = wiimote;
		this.fromRealToSoundQ = fromRealToSoundQ;
		this.toRumbleQ = toRumbleQ;
		this.toLEDQ = toLEDQ;
		
		
	}	
	
	private void initComponents() {
		//Speaker controller
		configSpeaker();
		setSoundMax();
		initSpeakerController();
		
		//Rumble controller
		initRumbleController();
		
		//LED controller
		initLedController();
		
	}
	
	@Override
	public void run() {		
		initComponents();
	}	
	
	
	/***************************************************
	// SOUND INIT METHODS
	****************************************************/
	
	private void initSpeakerController(){
		//wake up the speaker controller
		PermanenSoundController speakerController = (PermanenSoundController) 
			new PermanenSoundController(wiimote, fromRealToSoundQ);		
		
		executor.execute(speakerController);		
	}
	
	private void configSpeaker(){		
		//by default apcm configuration is set		
		Future<AtomicBoolean> future = 
    		executor.submit(new ActivateSpeaker(wiimote, wiimoteStatus.getSpeakerStatus()));    		
    		
    	try {
    		AtomicBoolean answer = future.get();    		
    		if(answer != null){    		
    			System.out.println("Answer from SpeakerConfig: " + answer);
    			wiimoteStatus.setSpeakerStatus(answer);    			
    		}    			    		
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}			
		
			
	}
	
	private void setSoundMax(){
		int i;		
		for(i = 0; i<=7; i++){
			wiimote.turnVolumeUp();			
		}
		
	}
	
	
	/***************************************************
	// SOUND INTERFACE
	****************************************************/
	
	@Override
	public void turnVolumeDown() {	
		Future<Boolean> future = 
			executor.submit(new VolumeSpeakerTask(wiimote, wiimoteStatus.getSpeakerStatus(), 0));
	}
	@Override
	public void turnVolumeUp() {	
		Future<Boolean> future = 
			executor.submit(new VolumeSpeakerTask(wiimote, wiimoteStatus.getSpeakerStatus(), 1));		
	}
	
	
	/***************************************************
	// RUMBLE INIT METHODS
	****************************************************/
	
	protected void initRumbleController(){		
		PermanentRumbleController rumbleController = 
			new PermanentRumbleController(wiimote, toRumbleQ, executor);
		
		executor.execute(rumbleController);
		
	}
	
	/***************************************************
	// LED INIT METHODS
	****************************************************/
	private void initLedController(){
		Runnable ledController = 
			new PermanentLEDContoller(wiimote, toLEDQ);
		
		executor.execute(ledController);		
	}



	
	
}
